/* @flow */

/**
 * 检测一个字符串是否以 $ 或者 _ 开头: 主要用来判断一个字段的键名是否是保留的, 如 vue中不允许$和_开头作为data数据的字段名
 */
export function isReserved (str: string): boolean {
  const c = (str + '').charCodeAt(0)
  // 对比其16进制值
  return c === 0x24 || c === 0x5F
}

/**
 * 对 Object.defineProperty 函数的简单包装.
 * obj: 源对象
 * key: 要在源对象上添加的key
 * val: 与key对应的值
 * enumerable: 是否可枚举
 */
export function def (obj: Object, key: string, val: any, enumerable?: boolean) {
  Object.defineProperty(obj, key, {
    value: val,
    enumerable: !!enumerable,
    writable: true,
    configurable: true
  })
}

/**
 * Parse simple path.
 */
// 正则：用来匹配 obj.a、this.$watch的格式
const bailRE = /[^\w.$]/
export function parsePath (path: string): any {
  // 使用正则匹配path，如果匹配(obj~a、obj/a、obj*a、obj+a均能匹配)则直接返回，且返回值为 undefined
  if (bailRE.test(path)) {
    return
  }
  const segments = path.split('.')
  // 分隔path，并返回一个新函数：且返回的接函数作为 this.getter 的值
  return function (obj) {
    for (let i = 0; i < segments.length; i++) {
      // 遍历 segments 数组循环访问 path 指定的属性值。这样就可以触发数据属性的 get 拦截器函数
      if (!obj) return
      obj = obj[segments[i]]
    }
    return obj
  }
}
